/* fastPathLib.h - Definitions for the Fastpath library  */

/*
 * Copyright (c) 1984-2005 Wind River Systems, Inc.
 *
 * The right to copy, distribute or otherwise make use of this software
 * may be licensed only pursuant to the terms of an applicable Wind River
 * license agreement. No license to Wind River intellectual property rights
 * is granted herein. All rights not licensed by Wind River are reserved
 * by Wind River.
 */

/*
modification history
--------------------
01r,21apr05,kch  Removed unused FF_GET_SCOPE_ID macro.
01q,01mar05,niq  Fix the ipFFInit API (SPR 102586)
01p,02oct04,niq  Backward compatibility change
01o,28may04,niq  Merging from base6 label POST_ITER5_FRZ16_REBASE
01n,20nov03,niq  Remove copyright_wrs.h file inclusion
01m,05nov03,cdw  Removal of unnecessary _KERNEL guards.
01l,04nov03,rlm  Ran batch header path update for header re-org.
01k,15sep03,vvv  updated path for new headers
01j,20mar03,niq  Reorganize the locking model and fix locking bugs + Revert to
                 published API names for backwards compatilibility
01i,19mar03,niq  Expand the ffRouteAdded API
01h,13mar03,niq  Fastpath forwarding hook integration
01g,12mar03,niq  Add a few macros - v4/v6 consolidation
01f,13feb03,deg  include path for if_dl.h fixed
01e,06feb03,deg  change type of macAddr in ffPubFibEntry to struct sockaddr_dl
01d,04feb03,deg  include path changed
01c,24jan03,deg  ff_config_params changed
01b,14nov02,deg  #include <netinet/vsLib.h> deleted
01a,07oct02,deg  written
*/

/*
DESCRIPTION
This file contains definitions used by the Fastpath library
and by the IPv4 & IPv6 Fast Forwarder modules.
 
*/

#ifndef __INCfastPathLibh
#define __INCfastPathLibh

/* includes */

#include <cfgDefs.h>
#include <sys/socket.h>
#include <net/if_dl.h>
#include <end.h>
#include <private/fastPathLibP.h>
#include <fastPath/fastPathFib.h>

/* defines */

/* Fastpath interface version */

#define FF_VERSION	0x00000011

/*
 * The following definitions define bitwise OR values for the ffIpv4State
 * and ffIpv6State variables
 */

#define FF_MODULE_NOT_INITIALIZED 0	/* Module (v4 or v6) not initialized*/
#define FF_MODULE_INITIALIZED	1	/* Module (v4 or v6) not initialized*/
#define FF_MODULE_STARTED	2	/* Calls can be made to module */
#define FF_MODULE_ENABLED	4	/* Fastforwarding is in effect */

/* errno values */

#define S_fastPathLib_ALREADY_EXISTS		(M_fastPathLib | 1)
#define S_fastPathLib_ALREADY_REGISTERED		(M_fastPathLib | 2)
#define S_fastPathLib_INTERNAL_ERROR		(M_fastPathLib | 3)
#define S_fastPathLib_INVALID_ARG		(M_fastPathLib | 4)
#define S_fastPathLib_INVALID_OBJ		(M_fastPathLib | 5)
#define S_fastPathLib_INVALID_PARAMS		(M_fastPathLib | 6)
#define S_fastPathLib_INVALID_PROTO		(M_fastPathLib | 7)
#define S_fastPathLib_INVALID_STATE		(M_fastPathLib | 8)
#define S_fastPathLib_NOT_FOUND			(M_fastPathLib | 9)
#define S_fastPathLib_NOT_INITIALIZED		(M_fastPathLib | 10)

/* Definitions for the Fast Forwarder (Hardware or Software) */

#define FF_HARDWARE_FORWARDER 0x01
#define FF_SOFTWARE_FORWARDER 0x02

/* Protocol types supported by FastPath */

#define FF_PROTO_IPV4 0x01
#define FF_PROTO_IPV6 0x02

/* Definition for unlimited FIB size */

#define FF_FIB_SIZE_UNLIMITED 0x00

/* Metric for routes passed onto the Fast Forwarder modules */

/*
 * We use -1 for FF_REP_ROUTE as the route weight can never equal that value.
 * We can't use zero as the route weight for all routes is zero for a
 * host stack
 */

#define FF_NON_REP_ROUTE 0x00	
#define FF_REP_ROUTE	-1 

/* Fastpath mode commands */

#define FF_START		0x01 /* Start the Fastpath module*/
#define FF_STOP		0x02 /* Stop the Fastpath module */
#define FF_ENABLE	0x04 /* Enable packet fast-forwarding */
#define FF_DISABLE	0x08 /* Disable packet fast-forwarding */
#define FF_IPFF_ENABLE	0x10 /* IP fast-forwarding enabled */
#define FF_IPFF_DISABLE 	0x20 /* IP fast-forwarding disabled */

/* Commands for interface status change call */

#define FF_IF_UP     	0x01
#define FF_IF_DOWN   	0x02
#define FF_IF_DELETE 	0x04
#define FF_IF_ADD    	0x08
#define FF_IFADDR_ADD    0x10
#define FF_IFADDR_DELETE	0x20

/* Flags for the ffRouteAdded command - bitwise OR */

#define FF_INTF_ROUTE 0x01

/* Fastpath object locking macros */

#define FF_LOCK_INIT(x) ((x) = semMCreate (SEM_Q_PRIORITY | SEM_DELETE_SAFE | \
                                           SEM_INVERSION_SAFE))     
#define FF_LOCK_DESTROY(x) (semDelete (x))
#define FF_OBJ_LOCK(pFFObj)     semTake((pFFObj)->ffCacheLock, WAIT_FOREVER)
#define FF_OBJ_UNLOCK(pFFObj)   semGive((pFFObj)->ffCacheLock)
#define FF_OBJ_CACHEWALK_LOCK(pFFObj) \
                  semTake((pFFObj)->ffCacheWalkLock, WAIT_FOREVER)
#define FF_OBJ_CACHEWALK_UNLOCK(pFFObj) \
                  semGive((pFFObj)->ffCacheWalkLock)


#define FF_DO_IP_FORWARDING  IP_DO_FORWARDING
#define FF_WE_ARE_FORWARDING 0x40000000

#define FF_FLAGS_IP_MASK (IP_DO_FORWARDING)

#define FF_GET_IP_FLAGS(pFFObj) ((pFFObj->ffFlags) & FF_FLAGS_IP_MASK)

#define FF_SET_IP_FLAGS(pFFObj, flags) \
                     (pFFObj->ffFlags = (pFFObj->ffFlags & ~FF_FLAGS_IP_MASK) | \
                                        (flags & FF_FLAGS_IP_MASK))

#define FF_SET_WE_ARE_FORWARDING(pFFObj) \
                     (pFFObj->ffFlags |= FF_WE_ARE_FORWARDING)
#define FF_RESET_WE_ARE_FORWARDING(pFFObj) (pFFObj->ffFlags &= \
					    ~FF_WE_ARE_FORWARDING)

/* Macros used by various components of the system  */

#define FF_ARE_WE_FORWARDING(pFFObj) (pFFObj->ffFlags & FF_WE_ARE_FORWARDING)

#define SHOULD_MAKE_CALLS_TO_FF(pFFObj)	((pFFObj != NULL) && \
					 FF_MOD_STARTED (pFFObj))

#define SHOULD_GIVE_PACKET_TO_FF(pFFObj, pIfp) \
    ((pFFObj != NULL) && \
     FF_ARE_WE_FORWARDING (pFFObj) && FF_MOD_ENABLED (pFFObj) && \
     FF_INTF_ENABLED (pFFObj, pIfp) && pFFObj->ffFuncTable->ffPktSend != NULL)

/* Call Fast Forwarder module functions (private macro ) */

#define FF_CALL(pFFObj, func, args) (((pFFObj != NULL) && \
                                    (SHOULD_MAKE_CALLS_TO_FF (pFFObj)) && \
                                    (pFFObj->ffFuncTable->func != NULL)) ? \
                                    (*(pFFObj->ffFuncTable->func)) args : \
					ERROR)

/* Same as above, except that checks have already been made */

#define FF_NC_CALL(pFFObj, func, args) \
                   (((pFFObj != NULL) && (pFFObj->ffFuncTable->func != NULL)) ? \
                   (*(pFFObj->ffFuncTable->func)) args : ERROR)

/* Definitions for the flags field - bitwise OR */

#define FF_PUB_ENTRY_FLAG_MAC	   0x01
#define FF_PUB_ENTRY_FLAG_VALID	   0x02
#define FF_PUB_ENTRY_FLAG_COMPLETE 0x04

/* Macros to test the state of the public FIB entry */

#define IS_FF_PUB_ENTRY_MAC(x)	((x)->flags & FF_PUB_ENTRY_FLAG_MAC)
#define IS_FF_PUB_ENTRY_NON_MAC(x) (!((x)->flags & FF_PUB_ENTRY_FLAG_MAC))
#define IS_FF_PUB_ENTRY_VALID(x) (((x)->flags & FF_PUB_ENTRY_FLAG_VALID))
#define IS_FF_PUB_ENTRY_INVALID(x) (!((x)->flags & FF_PUB_ENTRY_FLAG_VALID))
#define IS_FF_PUB_ENTRY_COMPLETE(x) (((x)->flags & FF_PUB_ENTRY_FLAG_COMPLETE))
#define IS_FF_PUB_ENTRY_INCOMPLETE(x)(!((x)->flags & FF_PUB_ENTRY_FLAG_COMPLETE))

#define SET_FF_LIB_LOG_LEVEL(x) ffLibLogLevel = (x)


/* Macro to retrieve the hardware assist status of an interface */
#define GET_HWASSIST_FLAGS(x)	(((struct ifnet *)(x))->if_hwassist)
  
/* Interface to get scope. Might change in the future */

#ifdef INET6
#define IPADDR_MASKED_ARE_SAME(pD, pN, pG) \
            ((pD->sa_family == AF_INET) ? \
             ((SOCKADDR_IN(pD) & SOCKADDR_IN(pN)) == \
              (SOCKADDR_IN(pG) & SOCKADDR_IN(pN))) : \
             ((pD->sa_family == AF_INET6) ? \
              (((SA6(pD).s6_addr32[0] & SA6(pN).s6_addr32[0]) == \
                (SA6(pG).s6_addr32[0] & SA6(pN).s6_addr32[0])) && \
               ((SA6(pD).s6_addr32[1] & SA6(pN).s6_addr32[1]) == \
                (SA6(pG).s6_addr32[1] & SA6(pN).s6_addr32[1])) && \
               ((SA6(pD).s6_addr32[2] & SA6(pN).s6_addr32[2]) == \
                (SA6(pG).s6_addr32[2] & SA6(pN).s6_addr32[2])) && \
               ((SA6(pD).s6_addr32[3] & SA6(pN).s6_addr32[3]) == \
                (SA6(pG).s6_addr32[3] & SA6(pN).s6_addr32[3]))) : \
              (panic ("BAD address family: %d %x @ %s:%d\n", \
                      pD->sa_family, pD, __FILE__, __LINE__), FALSE)))
#else
#define IPADDR_MASKED_ARE_SAME(pD, pN, pG) \
            ((pD->sa_family == AF_INET) ? \
             ((SOCKADDR_IN(pD) & SOCKADDR_IN(pN)) == \
              (SOCKADDR_IN(pG) & SOCKADDR_IN(pN))) : \
             (panic ("BAD address family: %d %x @ %s:%d\n", \
                     pD->sa_family, pD, __FILE__, __LINE__), FALSE))
#endif /* INET6 */

/* typedefs */

/* Generic Fast Forwarder object */

typedef struct ffObj
{
  NODE		      ffNode;              /* Internal */
  int		      ffVersion;	   /* Internal - fastpath module version */
  char 		      ffName[FF_NAME_MAX]; /* Name of Fast Forwarder module*/
  SEM_ID              ffCacheLock;    /* To synchronize access */
  SEM_ID              ffCacheWalkLock;/* To synchronize access */
  int		      ffFlags;	           /* IP config states */
  int 		      ffProto;	           /* Protocol type */
  int                 ffState;	           /* Fast Forwarder state */
  int 		      ffFibSize;	   /* Max # of FIB entries */
  struct ffFunctions *ffFuncTable;	   /* Table of function pointers*/
  void               *ffRouteHandle;       /* acc_deg: ? */
  void               *ffPrivate;	   /* Private data */
} FF_OBJ;

typedef FF_OBJ *FF_OBJ_ID;

/* The following macro return the address family for the given Fastpath obj */
#ifdef INET6
#define FP_TO_AF(x)  (((x)->ffProto == FF_PROTO_IPV4) ? AF_INET : \
		      (((x)->ffProto == FF_PROTO_IPV6) ? AF_INET6 : \
		       (panic ("BAD fastpath proto : %d @ %s:%d \n", \
			       (x)->ffProto, __FILE__, __LINE__), 0)))
#else
#define FP_TO_AF(x)  (((x)->ffProto == FF_PROTO_IPV4) ? AF_INET : \
		      (panic ("BAD fastpath proto : %d @ %s:%d \n", \
			      (x)->ffProto, __FILE__, __LINE__), 0))
#endif /* INET6 */

/*
 * Definition for the structure passed to the ffInterfaceStatusChanged
 * function 
 */

struct ffIfAddrArg 
    { 
    struct sockaddr * pIfaAddr; 
    struct sockaddr * pIfaNetmask; 
    };

/*
 * Definition of the structure that the ffFibWalk routine passes to the
 * user defined function. This is the public format in which the 
 * Fastpath FIB entries are exported.
 */

typedef struct ffPubFibEntry
{
  SOCKADDR_STORAGE_T dstAddr;
  SOCKADDR_STORAGE_T netmask;
  SOCKADDR_STORAGE_T gateAddr;
  struct sockaddr_dl macAddr;
  unsigned int	     routeMetric;
  unsigned int	     ifMtu;
  unsigned int	     ifIndex;
  unsigned int	     useCount;
  unsigned int	     refCount;
  unsigned int	     flags;
  void *	     pOutIfCookie;
} FF_PUB_FIB_ENTRY;

/* Prototype for the user defined function that ffFibWalk invokes */

typedef STATUS (* FF_USER_WALK_FUNC_ID) (FF_PUB_FIB_ENTRY *, void *);

/* Prototype for the user defined function that ffLibRouteTableWalk invokes */

typedef STATUS (* FF_USER_RT_WALK_FUNC_ID) (FF_OBJ_ID, struct rtentry *, void *);

/* Prototype for the user defined fastpath module init function */

typedef struct ffObj * (*FFINIT_FUNC_PTR)(int, int, FIB_DISPATCH_TBL *);

/*
 * Definition of the function table structure that a Fast Forwarder module
 * passes to the Fastpath library 
 */

typedef struct ffFunctions
    {
    STATUS (* ffShutdown)               (FF_OBJ *);
    BOOL   (* ffPktSend)                (FF_OBJ *,
					 struct sockaddr *,
					 M_BLK_ID , 
					 USHORT,
					 void *);
    STATUS (* ffRouteAdded)             (FF_OBJ *,
					 int,
					 int,
					 struct sockaddr *,
					 struct sockaddr *,
					 struct sockaddr *,
					 int,
					 int,
					 void *);
    STATUS (* ffRouteDeleted)           (FF_OBJ *,
					 int,
					 int,
					 struct sockaddr *,
					 struct sockaddr *,
					 struct sockaddr *);
    STATUS (* ffRouteModified)          (FF_OBJ *,
					 int,
					 int,
					 struct sockaddr *,
					 struct sockaddr *,
					 struct sockaddr *,
					 struct sockaddr *);
    STATUS (* ffRouteComplete)          (FF_OBJ *,
					 struct sockaddr *,
					 struct sockaddr *,
					 struct sockaddr *,
					 char *,
					 int, 
					 int,
					 int,
					 int,
					 void *);
    STATUS (* ffMacEntryDeleted)        (FF_OBJ *,
					 struct sockaddr *, 
					 struct sockaddr *);
    STATUS (* ffRouteDemoted)           (FF_OBJ *,
					 int,
					 struct sockaddr *,
					 struct sockaddr *,
					 struct sockaddr *);              
    STATUS (* ffRoutePromoted)          (FF_OBJ *,
					 int,
					 struct sockaddr *,
					 struct sockaddr *,
					 struct sockaddr *);            
    STATUS (* ffInterfaceModeChanged)   (FF_OBJ *,
					 int,
					 int);
    STATUS (* ffModeChanged)            (FF_OBJ *,
					 int);
    STATUS (* ffInterfaceStatusChanged) (FF_OBJ *,
					 int,
					 int,
					 void *);
    STATUS (* ffFibFlush)               (FF_OBJ *);
    STATUS (* ffFibWalk)                (FF_OBJ *,
					 FF_USER_WALK_FUNC_ID,
					 void *);
    } FF_FUNCTIONS;

typedef FF_FUNCTIONS *FF_FUNC_ID;

/* Structure used by the ffLibRouteTableWalk() function */

typedef struct userRtFuncArg
{
  struct ffObj            *pFFObj;
  FF_USER_RT_WALK_FUNC_ID  pUserFunc;
  void                    *pUserArg;
} USER_RT_FUNC_ARG;

typedef struct ff_config_params
{
  CFG_DATA_HDR		cfgh;
  FFINIT_FUNC_PTR       pIPv4FFInit;
  FFINIT_FUNC_PTR       pIPv6FFInit;
  FIB_DISPATCH_TBL *	pFfIPv4FibDispTable;
  FIB_DISPATCH_TBL *	pFfIPv6FibDispTable;
} FF_CONFIG_PARAMS;

#ifdef VIRTUAL_STACK
extern VS_REG_ID ffRegistrationNum;
#endif /* VIRTUAL_STACK */
extern FF_CONFIG_PARAMS ffDefaultConfigParams;

/* Exported variables */

#ifndef VIRTUAL_STACK
IMPORT int 	  ffLibLogLevel;
IMPORT FF_OBJ_ID  GET_IPV4_FF_ID;
#endif /* VIRTUAL_STACK */

/* function declarations */

IMPORT STATUS ffLibInit (FFINIT_FUNC_PTR	pIPv4FFInit, 
			 FFINIT_FUNC_PTR pIPv6FFInit, 
			 FIB_DISPATCH_TBL * pFfIPv4FibDispTable, 
			 FIB_DISPATCH_TBL * pFfIPv6FibDispTabl);
IMPORT STATUS ffLibShutdown               (FF_OBJ *pFFObj);
IMPORT STATUS ffLibObjInit                (FF_OBJ *pFFObj,
					   int numRoutes,
					   int proto,
					   char *pIdString,
					   FF_FUNC_ID pFuncTable,
					   void *pPrivateData);
IMPORT STATUS ffLibObjUnInit              (FF_OBJ *pFFObj);

IMPORT STATUS ffLibCachePopulate            (FF_OBJ *pFFObj);
IMPORT STATUS ffLibCacheUpdate              (FF_OBJ *,
					   int,
					   struct sockaddr *, 
					   struct sockaddr *,
					   struct sockaddr *,
					   int,
					   int,
					   unsigned int);

IMPORT STATUS ffLibCacheFlush               (FF_OBJ *pFFObj);
IMPORT STATUS ffLibCachePrint               (FF_OBJ *pFFObj);
IMPORT STATUS ffLibCacheDump                (FF_OBJ *pFFObj,
					   unsigned char *pMemPtr,
					   int size);

IMPORT STATUS ffLibRouteTableWalk         (FF_OBJ *pFFObj,
				           FF_USER_RT_WALK_FUNC_ID pUserFunc,
				           void *pUserArg);

IMPORT STATUS ffLibModeSet                (FF_OBJ *pFFObj,
					   int mode);
IMPORT STATUS ffLibModeGet                (FF_OBJ *pFFObj,
					   int * mode);
IMPORT STATUS ffLibInterfaceModeSet       (FF_OBJ *pFFObj,
					   int ifIndex,
					   int mode);
IMPORT STATUS ffLibInterfaceModeGet       (FF_OBJ *pFFObj,
					   int ifIndex,
					   int *mode);
IMPORT STATUS ffLibLogLevelSet            (int level);
IMPORT int    ffLibLogLevelGet            (void);
IMPORT void  *ffLibProtoCookieGet         (int proto);
IMPORT void  *ffLibIfCookieFromIfIndexGet (FF_OBJ * pFFObj,
					   unsigned short ifIndex);
IMPORT void  *ffLibIfCookieFromEndGet     (FF_OBJ * pFFObj,
					   struct end_object * pEnd);
IMPORT STATUS ffLibStatsUpdate            (FF_OBJ *pFFObj,
					   int len,
					   void *pInIfCookie,
					   void *pOutIfCookie,
					   int flags);

IMPORT STATUS ffLibRouteComplete          (FF_OBJ *,
					   struct sockaddr *,
					   struct sockaddr *, 
				           struct sockaddr *,
					   char *,
					   int,
					   int,
					   int, 
					   int,
					   void *);
IMPORT STATUS ffLibMacEntryDeleted        (FF_OBJ *,
					   struct sockaddr *, 
					   struct sockaddr *);

#endif /* __INCfastPathLibh */
